﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;


namespace VideoLink.Utility
{
    /// <summary>
    /// Класс, осуществляющий подсчёт статистики и выводящий информацию на экран
    /// </summary>
    public class Statistics
    {
        #region Private fields

        /// <summary>
        /// Контрол, на который будет выводиться информация
        /// </summary>
        private PropertyGrid parent;
        /// <summary>
        /// Передано байт
        /// </summary>
        private long outTrafic;
        /// <summary>
        /// Принято байт
        /// </summary>
        private long inTrafic;
        /// <summary>
        /// Скорость передачи в байтах
        /// </summary>
        private long outSpeed;
        /// <summary>
        /// Скорость приёма в байтах
        /// </summary>
        private long inSpeed;
        /// <summary>
        /// Время последнего обновления OutTrafic
        /// </summary>
        private DateTime lastOutTime;
        /// <summary>
        /// Время последнего обновления InTrafic
        /// </summary>
        private DateTime lastInTime;

        #endregion

        #region Public properties

        /// <summary>
        /// Контрол, на который будет выводиться информация
        /// </summary>
        [Browsable(false)]
        public PropertyGrid Parent
        {
            get
            {
                return parent;
            }
            set
            {
                if (parent != null)
                {
                    parent.SelectedObject = null;
                    parent.Refresh();
                }

                parent = value;

                if (parent != null)
                {
                    parent.SelectedObject = this;
                    parent.Refresh();
                }
            }
        }

        /// <summary>
        /// Передано байт
        /// </summary>
        [DisplayName("Отправлено")]
        [Category("Трафик")]
        [Description("Полный исходящий трафик")]
        public long OutTrafic
        {
            get { return outTrafic; }
            private set
            {
                var oldValue = outTrafic;
                outTrafic = value;
                RefreshOutSpeed(outTrafic - oldValue);
            }
        }

        /// <summary>
        /// Принято байт
        /// </summary>
        [DisplayName("Принято")]
        [Category("Трафик")]
        [Description("Полный входящий трафик")]
        public long InTrafic
        {
            get { return inTrafic; }
            private set
            {
                var oldValue = inTrafic;
                inTrafic = value;

                RefreshInSpeed(inTrafic - oldValue);
            }
        }

        /// <summary>
        /// Скорость передачи в байтах
        /// </summary>
        [DisplayName("Исходящая")]
        [Category("Скорость")]
        [Description("Скорость передачи, байт/с")]
        public long OutSpeed
        {
            get { return outSpeed; }
        }

        /// <summary>
        /// Скорость приёма в байтах
        /// </summary>
        [DisplayName("Входящая")]
        [Category("Скорость")]
        [Description("Скорость приёма, байт/с")]
        public long InSpeed
        {
            get { return inSpeed; }
        }
        
        #endregion

        /// <summary>
        /// Создать экзмепляр класса по умолчанию
        /// </summary>
        public Statistics()
        {
        }

        #region Public methods

        /// <summary>
        /// Создать экземпляр класса с указанным родительским контролом.
        /// </summary>
        /// <param name="parent">
        /// Контрол, на который будет выводиться статистика.
        /// </param>
        public Statistics(PropertyGrid parent)
        {
            Parent = parent;
        }

        /// <summary>
        /// Обновить родительский контрол в соответствии с данными статистики.
        /// </summary>
        public void Refresh()
        {
            if (parent != null)
                parent.Refresh();
        }

        /// <summary>
        /// Учесть в статистике указанное количество переданных байт
        /// </summary>
        /// <param name="count">
        /// Количество переданных байт
        /// </param>
        public void BytesSent(long count)
        {
            OutTrafic += count;
        }

        /// <summary>
        /// Учесть в статистике указанное количество принятых байт
        /// </summary>
        /// <param name="count">
        /// Количество принятых байт
        /// </param>
        public void BytesReceived(long count)
        {
            InTrafic += count;
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Пересчтитать скорость передачи.
        /// </summary>
        /// <param name="delta">
        /// Количество байт, переданное с момента lastOutTime
        /// </param>
        private void RefreshOutSpeed(long delta)
        {
            var curTime = DateTime.Now;
            var dtime = curTime - lastOutTime;
            lastOutTime = curTime;

            outSpeed = (long)(delta / dtime.TotalSeconds);

            Refresh();
        }

        /// <summary>
        /// Пересчтитать скорость приёма.
        /// </summary>
        /// <param name="delta">
        /// Количество байт, переданное с момента lastInTime
        /// </param>
        private void RefreshInSpeed(long delta)
        {
            var curTime = DateTime.Now;
            var dtime = curTime - lastInTime;
            lastInTime = curTime;

            inSpeed = (long)(delta / dtime.TotalSeconds);

            Refresh();
        }
        
        #endregion
    }
}
